<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>ES5-隐式原型和显示原型的区别</title>
    <!-- 
  在 JavaScript 中， `__proto__`  和  `prototype`  是两个与对象原型链相关的概念，但它们有不同的用途和含义。
  一、 `prototype` 
  1. 定义：
    -  `prototype`  是一个对象，所有函数（尤其是构造函数）都有一个  `prototype`  属性。这个属性用于定义实例对象的原型。

  2. 用途：
    - 当使用构造函数创建对象时，新对象会继承构造函数的  `prototype`  属性上的属性和方法。

  3. 示例：
    function Person(name) {
        this.name = name;
    }

    Person.prototype.sayHello = function() {
        console.log(`你好，我是 ${this.name}`);
    };

    const person1 = new Person('小明');
    person1.sayHello(); // 输出: 你好，我是 小明
  4. 原型链：
    - 当访问对象的属性或方法时，JavaScript 会首先查找对象本身，如果找不到，则会查找其原型（即构造函数的  `prototype` ），然后再查找原型的原型，依此类推，直到找到或到达  `null` 。

  二、 `__proto__` 
  1. 定义：
    -  `__proto__`  是每个对象的一个内部属性，用于指向该对象的原型。它是一个指向对象原型的引用。

  2. 用途：
    -  `__proto__`  允许我们访问和修改对象的原型（尽管不推荐直接修改）。它是实现原型链的基础。

  3. 示例：
  const obj = {
        name: '小红'
    };

    const obj2 = Object.create(obj);
    console.log(obj2.__proto__ === obj); // 输出: true
    console.log(obj2.name); // 输出: 小红
  4. 访问原型：
    - 通过  `__proto__`  可以访问对象的原型，通常用于调试或查看原型链。

  三、主要区别

  | 特性               |  `prototype`                                |  `__proto__`                                  |
  |--------------------|------------------------------------------|---------------------------------------------|
  | 类型               | 是构造函数的属性                    | 是对象的属性                                |
  | 用途               | 定义构造函数的实例共享的属性和方法    | 用于访问和修改对象的原型                    |
  | 访问方式           | 通过构造函数访问                       | 通过对象实例访问                            |
  | 适用场景           | 用于创建继承和共享方法                 | 用于查看对象的原型链                        |

  四、总结
  -  `prototype`  是构造函数的一个属性，用于定义实例的原型和共享方法。
  -  `__proto__`  是每个对象的一个属性，指向该对象的原型，允许访问原型链。
  - 在使用时，建议使用  `Object.getPrototypeOf(obj)`  和  `Object.setPrototypeOf(obj, proto)`  来获取和设置原型，而不是直接使用  `__proto__` ，因为直接操作  `__proto__`  可能会导致性能问题和不必要的复杂性。
  --></head>

  <body>
    <script>
      // 1. __proto__ 是每个对象的属性，指向该对象的原型
      const obj = {
        name: "小明",
        age: 18,
      };
      console.log(obj.__proto__); // 输出: {constructor: ƒ, __defineGetter__: ƒ, __defineSetter__: ƒ, hasOwnProperty: ƒ, __lookupGetter__: ƒ, …

      // 2. prototype 是构造函数的属性，用于定义实例的原型和共享方法
      function Person(name, age) {
        this.name = name;
        this.age = age;
      }
      Person.prototype.sayHello = function () {
        console.log(`Hello, my name is ${this.name}`);
      };
      const person1 = new Person("小明", 18);
      const person2 = new Person("小红", 20);
      console.log(person1.__proto__ === Person.prototype); // 输出: true

      console.log(Array.prototype.__proto__ === Object.prototype); // 输出: true
      const arr = [];

      console.log(arr.__proto__ === Array.prototype);
      console.log(arr.__proto__.__proto__ === Object.prototype);
    </script>
  </body>
</html>
